﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;
using BL;
using Common;
using DAL.Model;
using DevExpress.XtraEditors;
using DevExpress.XtraGrid.Views.Base;
using DevExpress.XtraGrid.Views.Grid;
using UI.Helper;

namespace UI.MainFunctions
{
    public partial class frmTransfer : Base.DialogViewBase
    {
        #region Private variables

        private readonly FormAction _action;
        private MasterSession _session;
        private BindingList<TransferDetail> _transferDetails;
        private Transfer _transfer;
        private readonly int _transferId;
        private TransferController _transferController;
        private Product[] _products;
        private UnitOfMeasure[] _uoms;

        #endregion

        #region Constructor

        public frmTransfer()
        {
            InitializeComponent();
        }

        public frmTransfer(int transferId, FormAction action) : this()
        {
            _transferId = transferId;
            _action = action;
        }
        
        public frmTransfer(Transfer transfer, FormAction action, MasterSession session) : this()
        {
            _transfer = transfer;
            _action = action;
            _session = session;
        }

        #endregion

        #region Overided methods

        protected override void InitializeBO()
        {
            base.InitializeBO();
            if (_session == null)
            {
                _session = new MasterSession();
            }
            _transferController = new TransferController(_session);
        }

        protected override void PopulateStaticData()
        {
            base.PopulateStaticData();
            LoadCustomers();
            LoadUoms();
        }

        protected override void PopulateData()
        {
            base.PopulateData();

            if(_action != FormAction.New && _transfer == null)
            {
                // edit/view mode
                _transfer = _session.Transfers
                    .FirstOrDefault(t => t.Id == _transferId);
            }

            _transferDetails = new BindingList<TransferDetail>(_transfer != null
                                                                   ? _transfer.TransferDetails.ToList()
                                                                   : new List<TransferDetail>());
            dgTransferDetail.DataSource = _transferDetails;
            gvTransferDetail.BestFitColumns();
            BindingData();
            LoadProducts();
            switch (_action)
            {
                case FormAction.View:
                    DisableEditor();
                    break;
            }

            PrecisionHelper.FormatCurencyPrecision(gcStockInQuantity,
                                                   gcStockOutQuantity,
                                                   gcMassQuantity,
                                                   gcQuantity);
        }

        protected override void FormatPrecision()
        {
            PrecisionHelper.FormatCurencyPrecision(gcMassQuantity,
                                                   gcQuantity,
                                                   gcStockInQuantity,
                                                   gcStockOutMassQuantity,
                                                   gcStockOutQuantity);
        }

        #endregion

        #region Private methods

        private void DisableEditor()
        {
            txtDocumentNo.Properties.ReadOnly = true;
            deStockedDate.Properties.ReadOnly = true;
            lueCustomers.Properties.ReadOnly = true;
            gvTransferDetail.OptionsBehavior.Editable = false;
            spSave.Enabled = false;
        }

        private void BindingData()
        {
            txtDocumentNo.DataBindings.Add("Text", _transfer, "DocumentNo");
            deStockedDate.DataBindings.Add("EditValue", _transfer, "StockedDate");
            lueCustomers.DataBindings.Add("EditValue", _transfer, "CustomerId");
        }

        private void LoadCustomers()
        {
            var customers = _session.Customers.ToArray();
            lueCustomers.Properties.DataSource = customers;
            //lueCustomers.Enabled = false;
        }

        private void LoadUoms()
        {
            _uoms = _session.UnitOfMeasures.ToArray();
            lueUOM.DataSource = _uoms;
        }

        private void LoadProducts()
        {
            _products = _transfer.TransferDetails
                .Select(t => t.Product)
                .ToArray();
            lueProducts.DataSource = _products;
        }

        private bool ValidateData()
        {
            var validated = true;

            if (string.IsNullOrEmpty(_transfer.DocumentNo))
            {
                txtDocumentNo.ErrorText = "Nhập số phiếu.";
                validated = false;
            }
            else
            {
                txtDocumentNo.ErrorText = string.Empty;
            }
            if (!CommonHelper.IsValidDate(_transfer.StockedDate))
            {
                deStockedDate.ErrorText = "Ngày xuất không hợp lệ.";
                validated = false;
            }
            else
            {
                deStockedDate.ErrorText = string.Empty;
            }

            if (txtDocumentNo.ErrorText != string.Empty)
            {
                return validated;
            }

            if (!_transfer.TransferDetails.Any())
            {
                txtDocumentNo.ErrorText = "Nhập chi tiết hàng hóa.";
                validated = false;
            }
            else
            {
                txtDocumentNo.ErrorText = string.Empty;
            }

            var transfer = _session.Transfers
                .FirstOrDefault(t => t.Id != _transfer.Id &&
                                     t.DocumentNo == _transfer.DocumentNo);
            if (transfer != null && _transfer.Id != transfer.Id)
            {
                txtDocumentNo.ErrorText = "Mã phiếu đã tồn tại";
                validated = false;
            }
            else
            {
                txtDocumentNo.ErrorText = string.Empty;
            }

            if(_transferDetails.Any(detail => string.IsNullOrWhiteSpace(detail.Specifical)))
            {
                gvTransferDetail.SetColumnError(FormHelper.GetColumn(gvTransferDetail, "Specifical"), "Nhập quy cách");
                validated = false;
            }

            return validated;
        }

        #endregion
        
        private void spCancel_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void spSave_Click(object sender, EventArgs e)
        {
            if (!ValidateData())
            {
                return;
            }

            _transferController.PrepareSavingData(_transfer);

            _session.CommitChanges();
            Close();
        }

        private void gvTransferDetail_InitNewRow(object sender, InitNewRowEventArgs e)
        {
            var transferDetail = (TransferDetail) gvTransferDetail.GetRow(gvTransferDetail.FocusedRowHandle);
            if (transferDetail == null)
            {
                return;
            }
            transferDetail.Transfer = _transfer;

            _transfer.TransferDetails.Add(transferDetail);
        }

        private void lueProducts_EditValueChanged(object sender, EventArgs e)
        {
            var lookUpEdit = sender as LookUpEdit;
            // if not select product yet
            if (lookUpEdit == null || lookUpEdit.EditValue == null)
            {
                return;
            }

            var transferDetail = (TransferDetail)gvTransferDetail.GetRow(gvTransferDetail.FocusedRowHandle);
            // if cannot get current row
            if (transferDetail == null)
            {
                return;
            }

            transferDetail.Product = _products
                .FirstOrDefault(t => t.Id == (int)lookUpEdit.EditValue);

            var detail = _transferDetails
                .FirstOrDefault(t => t.ProductId == (int)lookUpEdit.EditValue);
            if (detail == null)
            {
                return;
            }

            transferDetail.StockInQuantity = detail.StockInQuantity;
            transferDetail.StockInDetail = detail.StockInDetail;
            transferDetail.StockOutQuantity = detail.StockOutQuantity;
        }

        private void lueUOM_EditValueChanged(object sender, EventArgs e)
        {
            var lookUpEdit = sender as LookUpEdit;
            // if not select product yet
            if (lookUpEdit == null || lookUpEdit.EditValue == null)
            {
                return;
            }

            var transferDetail = (TransferDetail)gvTransferDetail.GetRow(gvTransferDetail.FocusedRowHandle);
            // if cannot get current row
            if (transferDetail == null)
            {
                return;
            }

            transferDetail.UnitOfMeasure = _uoms
                .FirstOrDefault(t => t.Id == (int)lookUpEdit.EditValue);
        }

        private void gvTransferDetail_ValidateRow(object sender, ValidateRowEventArgs e)
        {
            var transferDetail = (TransferDetail)gvTransferDetail.GetRow(gvTransferDetail.FocusedRowHandle);
            // if cannot get current row
            if (transferDetail == null)
            {
                return;
            }

            gvTransferDetail.ClearColumnErrors();

            if (transferDetail.Product == null)
            {
                gvTransferDetail.SetColumnError(FormHelper.GetColumn(gvTransferDetail, "Product.Id"), "Chọn sản phẩm");
                e.Valid = false;
            }
            if (string.IsNullOrEmpty(transferDetail.Specifical))
            {
                gvTransferDetail.SetColumnError(FormHelper.GetColumn(gvTransferDetail, "Specifical"), "Nhập quy cách");
                e.Valid = false;
            }
            if (transferDetail.StockInQuantity < 0)
            {
                gvTransferDetail.SetColumnError(FormHelper.GetColumn(gvTransferDetail, "StockInQuantity"), "Số lượng nhập không hợp lệ");
                e.Valid = false;
            }
            if (transferDetail.MassQuantity < 0)
            {
                gvTransferDetail.SetColumnError(FormHelper.GetColumn(gvTransferDetail, "MassQuantity"), "Khối lượng không hợp lệ");
                e.Valid = false;
            }
            if (transferDetail.Quantity < 0)
            {
                gvTransferDetail.SetColumnError(FormHelper.GetColumn(gvTransferDetail, "Quantity"), "Số lượng không hợp lệ");
                e.Valid = false;
            }
        }

        private void gvTransferDetail_InvalidRowException(object sender, InvalidRowExceptionEventArgs e)
        {
            e.ExceptionMode = DevExpress.XtraEditors.Controls.ExceptionMode.NoAction;
        }

        private void gvTransferDetail_KeyDown(object sender, KeyEventArgs e)
        {
            TransferDetail detail;
            var isNewItemRow = gvTransferDetail.IsNewItemRow(gvTransferDetail.FocusedRowHandle);
            switch (e.KeyData)
            {
                case Keys.Escape:
                    if (!isNewItemRow)
                    {
                        return;
                    }
                    detail = (TransferDetail)gvTransferDetail.GetRow(gvTransferDetail.FocusedRowHandle);
                    if (detail == null)
                    {
                        return;
                    }
                    _session.TransferDetails.Remove(detail);
                    break;
                case Keys.F2:
                    if (isNewItemRow)
                    {
                        return;
                    }
                    detail = (TransferDetail)gvTransferDetail.GetRow(gvTransferDetail.FocusedRowHandle);
                    if (detail == null || detail.Product == null)
                    {
                        return;
                    }

                    var newDetail = _transferController.CreateDetail(_transfer);
                    newDetail.StockInDetail = detail.StockInDetail;
                    newDetail.Product = detail.Product;
                    newDetail.Product.Code = detail.Product.Code;
                    newDetail.Product.Name = detail.Product.Name;
                    newDetail.Product.ProductCategory = detail.Product.ProductCategory;
                    newDetail.Product.ProductCategoryId = detail.Product.ProductCategoryId;
                    newDetail.UnitOfMeasure = detail.UnitOfMeasure;
                    newDetail.Quantity = detail.Quantity;
                    newDetail.MassQuantity = detail.MassQuantity;
                    newDetail.StockInQuantity = detail.StockInQuantity;
                    _transferDetails.Add(newDetail);

                    break;
                case Keys.Delete:
                    if (isNewItemRow)
                    {
                        return;
                    }
                    if (_transfer.TransferDetails.Count == 1)
                    {
                        return;
                    }

                    if (DialogResult.No == MessageBox.Show("Bạn muốn xóa dòng đang chọn?",
                                                           "Xác nhận",
                                                           MessageBoxButtons.YesNo))
                    {
                        return;
                    }

                    detail = (TransferDetail)gvTransferDetail.GetRow(gvTransferDetail.FocusedRowHandle);
                    _session.TransferDetails.Remove(detail);
                    gvTransferDetail.DeleteRow(gvTransferDetail.FocusedRowHandle);
                    break;
                default:
                    return;
            }
        }
    }
}
